home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / go / prog / xigcv2_8.taz / xigcv2_8 / xigc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-08  |  33.4 KB  |  1,351 lines

  1. /* xigc.c
  2.  * S.Coffin    USWAT    1/93
  3.  *
  4.  * Main X11 program for displaying Goban widget, menus, and etc
  5.  */
  6.  
  7. /*  Copyright (c) 1992 by Stephen Coffin.  All rights reserved.
  8.  *
  9.  *  This program is distributed in the hope that it will be useful.
  10.  *  Use and copying of this software and preparation of derivative works
  11.  *  based upon this software are permitted, so long as the following
  12.  *  conditions are met:
  13.  *       o credit to the authors is acknowledged following current
  14.  *         academic behavior
  15.  *       o no fees or compensation are charged for use, copies, or
  16.  *         access to this software
  17.  *       o this copyright notice is included intact.
  18.  *  This software is made available AS IS, and no warranty is made about 
  19.  *  the software or its performance. 
  20.  * 
  21.  *  Bug descriptions, use reports, comments or suggestions are welcome.
  22.  *  Send them to    scoffin@advtech.uswest.com
  23.  */
  24.  
  25. /* uncomment this if you get X error "Attempt to access private resource
  26.  * failed"  (XGrabKey)   =SC
  27.  */
  28. /*SC #define NOKEYGRAB SC*/
  29.  
  30. #include <stdio.h>
  31. #include <X11/Intrinsic.h>
  32. #include <X11/Shell.h>
  33. #include <X11/StringDefs.h>
  34. #include <X11/Xlib.h>
  35. #include <X11/Xutil.h>
  36. #include <X11/cursorfont.h>
  37. #include <X11/Xaw/Command.h>
  38. #include <X11/Xaw/Form.h>
  39. #include <X11/Xaw/Box.h>
  40. #include "filter.h"
  41. #include "shared.h"
  42. #include "stipple.bm"
  43.  
  44. /* the default communications command to execute */
  45. #define CMD "igscomm -h 128.91.11.53 -p 6969"
  46. /* the command to kill the communications proc */
  47. #define QUITCMD "."
  48.  
  49. /* Use of telnet not recommended =SC */
  50. /* #define CMD "telnet 128.91.11.53 6969" */
  51. /* #define QUITCMD "\nquit" */
  52.  
  53. /* #define CMD "rlogin uswat" */
  54. /* #define QUITCMD "~." */
  55.  
  56. /* #define CMD "cu uswat" */
  57. /* #define QUITCMD "~." */
  58.  
  59. #define USAGE "%s [x-arg-list] [-?] [-c \"command line to execute\"] [-d] [-s]\n"
  60. #define TITLE "xigc Menu"
  61. #define ICONTITLE "xigc Menu"
  62. #define BOARDTITLE "xigc"
  63. #define BOARDICON "xigc Board"
  64.  
  65. unsigned char cmdline[80];
  66. extern int move;
  67. extern int stepmove;
  68. int currentmove;
  69. unsigned char stippleflag = FALSE;
  70. unsigned char *cmd[80], *quitcmd[80];
  71. static void ClearBoard();
  72. int tersemode = FALSE;
  73. int sortwhomode = FALSE;
  74. extern unsigned char my_moveflag;
  75. extern int putout();
  76.  
  77. #include "Goban.h"
  78. void SetCursor ();
  79. void read_filter(), read_kbd(), read_pipe();
  80. int setup_filter();
  81. int input0id, input1id, input2id;
  82. int i0id, i1id, i2id;
  83. XtAppContext   app_context;
  84. int dbg = FALSE;
  85. static int cmdflag = FALSE;
  86. static int saveformat = TEXT;
  87. static int get_cmd();
  88. int boardchanged = FALSE;
  89. int mouseflag = FALSE;
  90. unsigned char statusflag = FALSE;
  91. static unsigned char savedir[80];
  92.  
  93. /* these fp's are the std i/o when we EXEC a process */
  94. FILE *exec_stdin=NULL, *exec_stdout=NULL, *exec_stderr=NULL;
  95. int gameno=(-1);
  96. int handicap = 0;
  97. extern unsigned char observeflag;
  98. int boardsize = 19;
  99. unsigned char player1[20], player2[20];
  100. int p1_sec, p2_sec;
  101. int p1_captured, p2_captured;
  102. int p1_byoyomi, p2_byoyomi;
  103. extern char rank1[], rank2[];
  104. extern float komi;
  105.  
  106. Widget toplevel, bw, goban, refresh, clearb, form, size, coordinates;
  107. Widget stepf, stepb, refreshstep, savecurrent;
  108. Widget cursorcolor, savegame, localrefresh, quit;
  109. Widget gamew, hcapw, whitew, blackw, captw, captb, timew, timeb, lastw;
  110.  
  111. #define MAXSIZE 19
  112. int colorflag = BLACK;
  113.  
  114. beep() {
  115.     XBell( XtDisplay(toplevel), 0 );
  116. }
  117.  
  118. highlight( flag )
  119.     int flag;
  120. {
  121.     static int ff = FALSE;
  122.     int j;
  123.     Arg args[2];
  124.     Pixel fg, bg, xx;
  125.  
  126.     /* switch highlighting */
  127.     if( (flag && !ff) || (!flag && ff) ) {
  128.         j = 0;
  129.         XtSetArg( args[j], XtNforeground, &fg ); ++j;
  130.         XtSetArg( args[j], XtNbackground, &bg ); ++j;
  131.         XtGetValues( localrefresh, args, j );
  132.         xx = fg;
  133.         fg = bg;
  134.         bg = xx;
  135.         j = 0;
  136.         XtSetArg( args[j], XtNforeground, fg ); ++j;
  137.         XtSetArg( args[j], XtNbackground, bg ); ++j;
  138.         XtSetValues( localrefresh, args, j );
  139.  
  140.         ff = flag;
  141.     }
  142. }
  143.  
  144. clearit() {
  145.     GbClearBoard( goban );
  146. }
  147.  
  148. void Quit( w, client_data, call_data )
  149.     GobanWidget w;
  150.     XtPointer client_data, call_data;
  151. {
  152.     if( cmdflag ) {
  153.         beep();
  154.         fprintf( stderr,
  155.         "\nLOCAL: you must log out of IGS and each intermedate system manually\n" );
  156.         fprintf( stderr, " when using the \"-c\" option\n" );
  157.         fprintf( exec_stdin, "\n" );
  158.         fflush( exec_stdin );
  159.         return;
  160.     }
  161.  
  162.     fprintf( exec_stdin, "quit\n" );
  163.     fflush( exec_stdin );
  164.     sleep( 1 );
  165.  
  166.     if( quitcmd[0] == '\0' )
  167.         fprintf( exec_stdin, "\n%s\n", QUITCMD );
  168.     else
  169.         fprintf( exec_stdin, "\n%s\n", quitcmd );
  170.     fflush( exec_stdin );
  171.     sleep( 1 );
  172.     rdwr_pclose( NULL, NULL, NULL );
  173.     exit( 0 );
  174. }
  175.  
  176. static void SaveGame( w, client_data, call_data )
  177.     GobanWidget w;
  178.     XtPointer client_data, call_data;
  179. {
  180.     unsigned char s[40], s2[40];
  181.     int ret;
  182.     struct stat sbuf;
  183.  
  184.     if( dbg )
  185.         fprintf( stderr, "IN SAVEGAME call_data=0x%x\n", client_data );
  186.  
  187.     if( (client_data == (XtPointer)REALMOVE && (gameno < 0 || move < 1) ) ||
  188.         (client_data == (XtPointer)STEPMOVE && currentmove < 0 ) ) {
  189.         beep();
  190.         fprintf( stderr, "\nLOCAL:  No active game to save\n" );
  191.         fflush( stderr );
  192.     }
  193.     else {
  194.         if( (int)strlen( (char *)player1 ) <= 0 || (int)strlen( (char *)player2 ) <= 0 )
  195.         strcpy( (char *)s, "no_players" );
  196.         else sprintf( (char *)s, "%s-%s", player1, player2 );
  197.  
  198.         /* find an unused filename */
  199.         sprintf( (char *)s2, "%s/%s", savedir, s );
  200.         for( ret = 1 ;; ++ret ) {
  201.         if( stat( (char *)s2, &sbuf ) == 0 ) {
  202.             sprintf( (char *)s2, "%s/%s.%d", savedir, s, ret );
  203.             continue;
  204.         }
  205.         else break;
  206.         }
  207.  
  208.         if( saveformat == SGF )
  209.             ret = save_game_sgf( s2, player1, player2, handicap,
  210.                         client_data );
  211.         else
  212.             ret = save_game( s2, player1, player2, handicap, client_data );
  213.         if( ret ) {
  214.            fprintf( stderr, "\nLOCAL:  Game saved to %s\n", s2 );
  215.            fflush( stderr );
  216.         }
  217.     }
  218.     fprintf( exec_stdin, "\n" );
  219.     fflush( exec_stdin );
  220.     return;
  221. }
  222.  
  223. set_cursor_color( m )
  224.     int m;
  225. {
  226.     if( m % 2 ) {
  227.         colorflag = BLACK;
  228.         SetCursor( GbCBlackStone );
  229.     }
  230.     else {
  231.         colorflag = WHITE;
  232.         SetCursor( GbCWhiteStone );
  233.     }
  234.     return( colorflag );
  235. }
  236.         
  237.  
  238. void do_refresh( m, type )
  239.     int m;
  240.     int type;
  241. {
  242.     int i, x, y, flag;
  243.  
  244.     GbClearBoard( goban );
  245.     initboard( boardsize );
  246.  
  247.     /* handle handicap */
  248.     if( handicap > 0 ) {
  249.         sethandicap( handicap, type );
  250.         i = 1;
  251.     }
  252.     else i = 0;
  253.  
  254.     update_handicap( handicap, komi );
  255.  
  256.     for( ; i <= m; ++i ) {
  257.         getmove( i, &x, &y, &flag );
  258.         if( i%2 ) {
  259.         makemove( x, y, i, GbCWhiteStone, type );
  260.         }
  261.         else {
  262.         makemove( x, y, i, GbCBlackStone, type );
  263.         }
  264.     }
  265.  
  266.     set_cursor_color( m );
  267. }
  268.  
  269. void RefreshStep( w, client_data, call_data )
  270.     GobanWidget w;
  271.     XtPointer client_data, call_data;
  272. {
  273.     int i;
  274.     int x, y;
  275.  
  276.     if( move < 0 || gameno < 0 ) {
  277.         beep();
  278.         highlight( FALSE );
  279.         fprintf( stderr, "\nLOCAL:  No active game to refresh\n" );
  280.         fflush( stderr );
  281.         fprintf( exec_stdin, "\n" );
  282.         fflush( exec_stdin );
  283.         return;
  284.     }
  285.     else if( stepmove < 0 || statusflag ) {
  286.         beep();
  287.         return;
  288.     }
  289.  
  290.     boardchanged = TRUE;
  291.     mouseflag = FALSE;
  292.     do_refresh( stepmove, STEPMOVE );
  293.     currentmove = stepmove;
  294.     if( stepmove >= move ) {
  295.         boardchanged = FALSE;
  296.         highlight( FALSE );
  297.     }
  298. }
  299.  
  300. void LocalRefresh( w, client_data, call_data )
  301.     GobanWidget w;
  302.     XtPointer client_data, call_data;
  303. {
  304.     int i;
  305.     int x, y;
  306.  
  307.     boardchanged = mouseflag = statusflag = FALSE;
  308.  
  309.     if( move < 0 || gameno < 0 ) {
  310.         beep();
  311.         highlight( FALSE );
  312.         fprintf( stderr, "\nLOCAL:  No active game to refresh\n" );
  313.         fflush( stderr );
  314.         highlight( FALSE );
  315.         GbClearBoard( goban );
  316.         fprintf( exec_stdin, "\n" );
  317.         fflush( exec_stdin );
  318.         initboard( boardsize );
  319.         return;
  320.     }
  321.  
  322.     do_refresh( move, REALMOVE );
  323.     stepmove = currentmove = move;
  324.     highlight( FALSE );
  325.     update_status( gameno, player2, player1, p2_captured, p1_captured,
  326.         p2_sec, p1_sec, p2_byoyomi, p1_byoyomi, rank1, rank2 );
  327.     update_handicap( handicap, komi );
  328. }
  329.  
  330. static unsigned char keyecho = TRUE;
  331.  
  332. /* This one processes keystrokes when the cursor is in the goban or menu
  333.  *
  334.  * adapted from code donated by loganj@byu.edu
  335.  *
  336.  * CNTRL-P causes echo to be suppressed until the next newline
  337.  */
  338.  
  339. #ifndef NOKEYGRAB
  340. static void keyevent( w, client_data, event, continue_flag )     /* BYU */
  341.     Widget w;
  342.     XtPointer client_data;
  343.     XEvent *event;
  344.     Boolean *continue_flag;
  345. {
  346.   int i;
  347.   KeySym ks;
  348.   XComposeStatus compose;
  349.   KeySym mykey;
  350.   static int tx = 0;
  351.   static unsigned char bst[4] = { 8,32,8,0 };
  352.   static unsigned char eol[3] = { 13,10,0 };
  353.   static unsigned char keytext[32], sendtext[128];
  354.  
  355.   switch (event->type) {
  356.     case KeyPress :
  357.     i = XLookupString( &event->xkey, (char *)keytext, 32, &mykey,
  358.             &compose );
  359.  
  360.     if( dbg ) fprintf( stderr,
  361.         "In keyevent KEYPRESS [i=%d, mykey=0x%x tx=%d]  keytext=>>%s<<\n",
  362.                 i, mykey, tx, keytext );
  363.  
  364.     if( i >= 1 && mykey >= 0 ) {
  365.         if( keytext[0] == '\n' || keytext[0] == '\r') {    /* newline */
  366.         fputs( (char *)eol, stderr );
  367.  
  368.             sendtext[tx++] = '\n';
  369.             sendtext[tx] = 0;
  370.  
  371.         /* got a line, now process it and send */
  372.         process_kbd( sendtext, exec_stdin );
  373.             tx = 0;
  374.             keyecho = TRUE;            /* Allow 1 line of no echo */
  375.         }
  376.         else if( keytext[0] == 0x15 ) {    /* delete */
  377.             while( tx > 0 ) { 
  378.                 tx--;
  379.                 if( keyecho ) fputs( (char *)bst, stderr );
  380.             }
  381.         }
  382.                         /* backspace */
  383.         else if( keytext[0] == 0x08 || mykey == (KeySym)(-1) ) {
  384.             if( tx > 0 ) { 
  385.                 tx--;
  386.                 if( keyecho ) fputs( (char *)bst, stderr );
  387.             }
  388.         }
  389.         else if( keytext[0] == 0x10 ) {    /* CNTRL-P */
  390.             if( keyecho ) keyecho = FALSE;
  391.             else keyecho = TRUE;
  392.         }
  393.         else if( tx < 127 && keytext[0] >= 0x20 ) {    /* normal char */
  394.             sendtext[tx++] = keytext[0];
  395.             keytext[1] = 0;
  396.             if( keyecho ) fputs( (char *)keytext, stderr );
  397.         }
  398.     }
  399.         break;
  400.     case MappingNotify:
  401.         XRefreshKeyboardMapping (&(event->xmapping));
  402.         break;
  403.     default:
  404.       if( dbg ) fprintf( stderr, "In keyevent Unknown Type 0x%x\n",
  405.         event->type );
  406.       break;
  407.   } 
  408.   fflush( stderr );
  409. }
  410. #endif /* NOKEYGRAB */
  411.  
  412. static void CursorColor( w, client_data, call_data )
  413.     GobanWidget w;
  414.     XtPointer client_data, call_data;
  415. {
  416.     makemove( (-1), (-1), ++currentmove, EMPTY, STEPMOVE );
  417.     boardchanged = mouseflag = TRUE;
  418.     highlight( TRUE );
  419.     set_cursor_color( colorflag+1 );
  420. }
  421.  
  422. static void StepForward( w, client_data, call_data )
  423.     GobanWidget w;
  424.     XtPointer client_data, call_data;
  425. {
  426.     int i, x, y, flag;
  427.  
  428.     if( move < 0 ) {
  429.         beep();
  430.         highlight( FALSE );
  431.         fprintf( stderr, "\nLOCAL:  No active game to step\n" );
  432.         fflush( stderr );
  433.         fprintf( exec_stdin, "\n" );
  434.         fflush( exec_stdin );
  435.         return;
  436.     }
  437.  
  438.     if( stepmove >= move || statusflag ) {
  439.         beep();
  440.         return;
  441.     }
  442.     else if( stepmove < 0 ) stepmove = 0;
  443.     else {
  444.         ++stepmove;
  445.         currentmove = stepmove;
  446.     }
  447.  
  448.     if( dbg )
  449.         fprintf( stderr, "StepForward entered [stepmove=%d, move=%d]\n",
  450.             stepmove, move );
  451.  
  452.     boardchanged = TRUE;
  453.  
  454.     if( mouseflag ) {
  455.         do_refresh( stepmove, STEPMOVE );
  456.         mouseflag = FALSE;
  457.     }
  458.     else {
  459.         if( stepmove == 0 && handicap > 0 ) {
  460.             sethandicap( handicap, STEPMOVE );
  461.         }
  462.         else {
  463.             getmove( stepmove, &x, &y, &flag );
  464.             if( stepmove % 2 ) {
  465.                 GbSetPoint( goban, x, y, GbWhiteStone, TRUE );
  466.                 makemove( x, y, stepmove, GbWhiteStone, STEPMOVE );
  467.         }
  468.             else {
  469.                 GbSetPoint( goban, x, y, GbBlackStone, TRUE );
  470.                 makemove( x, y, stepmove, GbBlackStone, STEPMOVE );
  471.         }
  472.         }
  473.     }
  474.  
  475.     if( stepmove < move ) boardchanged = TRUE;
  476.     else boardchanged = FALSE;
  477.  
  478.     set_cursor_color( stepmove );
  479.     if( stepmove >= move ) highlight( FALSE );
  480. }
  481.  
  482. static void StepBack( w, client_data, call_data )
  483.     GobanWidget w;
  484.     XtPointer client_data, call_data;
  485. {
  486.     int x, y, flag;
  487.  
  488.     if( dbg ) fprintf( stderr, "StepBack entered [stepmove=%d, move=%d]\n",
  489.             stepmove, move );
  490.  
  491.     if( move < 0 ) {
  492.         beep();
  493.         highlight( FALSE );
  494.         fprintf( stderr, "\nLOCAL:  No active game to step\n" );
  495.         fflush( stderr );
  496.         fprintf( exec_stdin, "\n" );
  497.         fflush( exec_stdin );
  498.         return;
  499.     }
  500.  
  501.     if( stepmove < 0 || statusflag ) {
  502.         beep();
  503.         return;
  504.     }
  505.     else if( stepmove > move ) stepmove = move;
  506.     else if( stepmove == 0 ) ClearBoard();
  507.     else {
  508.  
  509.         boardchanged = TRUE;
  510.  
  511.         /* only do full refresh if this move caused any captures, or if
  512.          * the board is dirty
  513.          */
  514.         getmove( stepmove, &x, &y, &flag );
  515.         if( !flag && !mouseflag ) {
  516.             GbSetPoint( goban, x, y, GbEmptyPoint, TRUE );
  517.         removemove( stepmove, STEPMOVE );
  518.             getmove( stepmove-1, &x, &y, &flag );
  519.             GbSetPoint( goban, x, y, (((stepmove-1)%2)+1), TRUE );
  520.         }
  521.         else {
  522.             do_refresh( stepmove-1, STEPMOVE );
  523.         mouseflag = FALSE;
  524.         }
  525.     }
  526.  
  527.     --stepmove;
  528.     currentmove = stepmove;
  529.     set_cursor_color( stepmove );
  530.     highlight( TRUE );
  531. }
  532.  
  533. static void InputStone( w, event )
  534.     GobanWidget w;
  535.     XButtonEvent *event;
  536. {
  537.     Position x = event->x;
  538.     Position y = event->y;
  539.  
  540.     if( GbGetStoneFromPosition( w, &x, &y ) == TRUE ) {
  541.         if( dbg ) fprintf( stderr, "Input stone at %c%d\n",
  542.                 'A' + (x > 8 ? x + 1 : x) - 1, y );
  543.     }
  544.     else {
  545.         beep();
  546.         return;
  547.     }
  548.  
  549.     if( observeflag != PLAYING && observeflag != SCORING ) {
  550.         beep();
  551.         return;
  552.     }
  553.  
  554.     fprintf( exec_stdin, "%c%d\n", 'A' + (x > 8 ? x + 1 : x) - 1, y );
  555.     fflush( exec_stdin );
  556.     if( !tersemode ) {
  557.         putout( "\n", FALSE, FALSE, 46 );
  558.     }
  559.     my_moveflag = TRUE;
  560. }
  561.  
  562. static void AlternateStone( w, event )
  563.     GobanWidget w;
  564.     XButtonEvent *event;
  565. {
  566.     int ob;
  567.     Position x = event->x;
  568.     Position y = event->y;
  569.  
  570.     if( GbGetStoneFromPosition( w, &x, &y ) == TRUE ) {
  571.         if( dbg ) fprintf( stderr, "Alternate stone at %c%d\n",
  572.                 'A' + (x > 8 ? x + 1 : x) - 1, y );
  573.     }
  574.     else {
  575.         beep();
  576.         return;
  577.     }
  578.  
  579.     if( statusflag ) {
  580.         beep();
  581.         return;
  582.     }
  583.  
  584.     ++currentmove;
  585.     if( gameno < 0 ) gameno = 0;
  586.     boardchanged = mouseflag = TRUE;
  587.     if( colorflag == BLACK ) {
  588.         GbSetPoint( goban, x, y, GbBlackStone, TRUE );
  589.         makemove( x, y, currentmove, GbBlackStone, STEPMOVE );
  590.     }
  591.     else {
  592.         GbSetPoint( goban, x, y, GbWhiteStone, TRUE );
  593.         makemove( x, y, currentmove, GbWhiteStone, STEPMOVE );
  594.     }
  595.     set_cursor_color( colorflag+1 );
  596.     highlight( TRUE );
  597. }
  598.  
  599.  
  600. static void RemoveStone( w, event )
  601.     GobanWidget w;
  602.     XButtonEvent *event;
  603. {
  604.     Position x = event->x;
  605.     Position y = event->y;
  606.  
  607.     if (GbGetStoneFromPosition (w, &x, &y) == TRUE) {
  608.         if( dbg ) fprintf ( stderr, "Remove stone at %c%d\n",
  609.                     'A' + (x > 8 ? x + 1 : x) - 1, y);
  610.     }
  611.  
  612.     if( statusflag ) {
  613.         beep();
  614.         return;
  615.     }
  616.  
  617.     /* XXX there is a slight glitch here: we do not remove stones
  618.      * from the board table, so they still interact when testing
  619.      * for dead stone removal and "Refresh(Local)"
  620.      */
  621.     GbSetPoint( goban, x, y, GbEmptyPoint, TRUE );
  622.  
  623.     boardchanged = mouseflag = TRUE;
  624.     highlight( TRUE );
  625. }
  626.  
  627. void Ticker( client_data, timer )
  628.     XtPointer client_data;
  629.     XtIntervalId *timer;
  630. {
  631.     XtAppAddTimeOut( (XtAppContext)client_data, 1000, Ticker, client_data );
  632.     if( move < 0 || !observeflag || statusflag ) return;
  633.  
  634.     else if( move % 2 ) {
  635.         if( FALSE ) fprintf( stderr, "TIMER EVEN [B]\n" );
  636.         --p2_sec;
  637.         fix_btime( p2_sec, p2_byoyomi );
  638.     }
  639.     else {
  640.         if( FALSE ) fprintf( stderr, "TIMER ODD [W]\n" );
  641.         --p1_sec;
  642.         fix_wtime( p1_sec, p1_byoyomi );
  643.     }
  644. }
  645.  
  646. void SetCursor ( cs )
  647.     int cs;
  648. {
  649.     Arg args[1];
  650.  
  651.     switch (cs) {
  652.         case GbCBlackStone : 
  653.         XtSetArg   (args[0], XtNcursor, GbCBlackStone);
  654.         if( dbg ) fprintf ( stderr, "Set cursor to : Black \n"); 
  655.         break;
  656.         case GbCWhiteStone : 
  657.         XtSetArg   (args[0], XtNcursor, GbCWhiteStone );
  658.         if( dbg ) fprintf ( stderr, "Set cursor to : White\n"); 
  659.         break;
  660.         case XC_question_arrow :
  661.         XtSetArg   (args[0], XtNcursor, XC_question_arrow );  
  662.         if( dbg ) fprintf ( stderr, "Set cursor to : Question\n"); 
  663.         break;
  664.     }
  665.  
  666.     XtSetValues (goban, args, 1);
  667. }
  668.  
  669. void RefreshHost( w, client_data, call_data )
  670.     GobanWidget w;
  671.     XtPointer client_data, call_data;
  672. {
  673.     if( gameno < 0 ) {
  674.         beep();
  675.         highlight( FALSE );
  676.         fprintf( stderr, "\nLOCAL:  No active game to refresh\n" );
  677.         fflush( stderr );
  678.         highlight( FALSE );
  679.         GbClearBoard( goban );
  680.         initboard( boardsize );
  681.         fprintf( exec_stdin, "\n" );
  682.         fflush( exec_stdin );
  683.     }
  684.     else {
  685.         SetCursor ( GbCBlackStone );
  686.         move = (-1);
  687.         refreshboard();
  688.         fprintf( exec_stdin, "moves %d\n", gameno );
  689.         fflush( exec_stdin );
  690.     }
  691. }
  692.  
  693. int refreshboard() {
  694.     if( gameno < 0 ) {
  695.         highlight( FALSE );
  696.         fprintf( stderr, "\nLOCAL: No active game to refresh\n" );
  697.         fflush( stderr );
  698.         fprintf( exec_stdin, "\n" );
  699.         fflush( exec_stdin );
  700.         return;
  701.     }
  702.  
  703.     boardchanged = mouseflag = statusflag = FALSE;
  704.     highlight( FALSE );
  705.     GbClearBoard( goban );
  706.     stepmove = (-1);
  707.     currentmove = (-1);
  708.     handicap = 0;
  709.     initboard( boardsize );
  710. }
  711.  
  712. static void ClearBoard() {
  713.     GbClearBoard( goban );
  714.     stepmove = (-2);
  715.     currentmove = (-1);
  716.     boardchanged = TRUE;
  717.     mouseflag = FALSE;
  718.     highlight( TRUE );
  719.     set_cursor_color( 1 );
  720.     clear_stepboard();
  721. }
  722.  
  723. void SetSize( w, client_data, call_data )
  724.     GobanWidget w;
  725.     XtPointer client_data, call_data;
  726. {
  727.  
  728.     Arg       args[1];
  729.     static int beenhere = FALSE;
  730.  
  731.     if( !beenhere ) boardsize = 13;
  732.  
  733.     if( call_data == NULL ) {
  734.         switch( boardsize ) {
  735.         case 9:
  736.             boardsize = 13;
  737.             break;
  738.         case 13:
  739.             boardsize = 19;
  740.             break;
  741.         case 19:
  742.         default:
  743.             boardsize = 9;
  744.             break;
  745.         }
  746.     }
  747.  
  748.     if( dbg ) fprintf ( stderr, "Set size to : %d\n", boardsize );
  749.  
  750.     if( beenhere ) {
  751.             stepmove = (-2);
  752.         currentmove = (-1);
  753.         boardchanged = FALSE;
  754.         mouseflag = FALSE;
  755.         highlight( FALSE );
  756.         initboard( boardsize );
  757.     }
  758.     else beenhere = TRUE;
  759.  
  760.     set_cursor_color( 1 );
  761.  
  762.     XtSetArg( args[0], XtNgameSize, (Dimension)boardsize );
  763.     XtSetValues( goban, args, 1 );
  764.  
  765. }
  766.  
  767. static void SetCoordinates() {
  768.     Arg     args[1];
  769.     Boolean coordinates;
  770.  
  771.     XtSetArg    (args[0], XtNdisplayCoordinates, &coordinates);
  772.     XtGetValues (goban, args, 1);
  773.     
  774.     switch (coordinates) {
  775.         case FALSE : 
  776.         XtSetArg (args[0], XtNdisplayCoordinates, TRUE) ; 
  777.         if( dbg ) fprintf( stderr, "Set coordinates to : TRUE \n");
  778.         break;
  779.         case TRUE  : 
  780.         XtSetArg (args[0], XtNdisplayCoordinates, FALSE); 
  781.         if( dbg ) fprintf( stderr, "Set coordinates to : FALSE \n");
  782.         break;
  783.     }
  784.  
  785.     XtSetValues (goban, args, 1);
  786. }
  787.  
  788. static void SetupBoard() {
  789.     unsigned char s[40];
  790.     
  791.     XtPopup( bw, XtGrabNone );
  792.     SetSize( NULL, NULL, NULL );
  793.     set_cursor_color( 1 );
  794.     sprintf( (char *)s, "%s [%s]", BOARDTITLE, PATCHLEVEL );
  795.     XSetStandardProperties( XtDisplay(bw), XtWindow(bw),
  796.             (char *)s, BOARDICON, NULL, NULL, 0, NULL );
  797.  
  798. }
  799.  
  800.  
  801.  
  802. static void Redisplay() {
  803.     GbRedisplayBoard (goban);
  804. }
  805.  
  806. XtActionsRec actions[] = {
  807.     { "inputStone", (XtActionProc)InputStone },
  808.     { "removeStone", (XtActionProc)RemoveStone },
  809.     { "addStone", (XtActionProc)AlternateStone },
  810. };
  811.  
  812. main( argc, argv )
  813.     int argc;
  814.     char **argv;
  815. {
  816.     extern void exit ();
  817.     extern unsigned char *optarg;
  818.     extern int optind;
  819.     int c;
  820.     int xtargc = 0;
  821.     Arg args[8];
  822.     int j;
  823.     extern int getopt();
  824.  
  825.     get_cmd();
  826.     if( cmd[0] == '\0' ) strcpy( (char *)cmdline, CMD );
  827.     else strcpy( (char *)cmdline, (char *)cmd );
  828.  
  829.     initboard( boardsize );
  830.     move = stepmove = (-1);
  831.     currentmove = (-1);
  832.     statusflag = FALSE;
  833.  
  834.     toplevel = XtAppInitialize( &app_context, "XIgc", NULL, 0, &argc, argv,
  835.             NULL, NULL, 0);
  836.  
  837.     /* any more command-line args? */
  838.     while( (c=getopt( argc, argv, "?c:ds" )) != (-1) ) {
  839.         switch( c ) {
  840.         case 'd':    /* debug mode */
  841.             dbg = TRUE;
  842.             break;
  843.         case 's':    /* stippled board */
  844.             stippleflag = TRUE;
  845.             break;
  846.         case 'c':    /* command line for comm program */
  847.             strcpy( (char *)cmdline, (char *)optarg );
  848.             cmdflag = TRUE;
  849.             break;
  850.         case '?':
  851.         default:
  852.             fprintf( stderr, "%s: Release %s\n", argv[0], PATCHLEVEL );
  853.                 fprintf( stderr, USAGE, argv[0] );
  854.             exit( (-1) );
  855.             break;
  856.         }
  857.     }
  858.  
  859.     if( optind != argc ) {
  860.         fprintf( stderr, "%s: Release %s\n", argv[0], PATCHLEVEL );
  861.         fprintf( stderr, USAGE, argv[0] );
  862.         exit( (-1) );
  863.     }
  864.  
  865.     bw = XtCreatePopupShell( "board", topLevelShellWidgetClass, toplevel,
  866.             NULL, 0);
  867.     form = XtCreateManagedWidget( "form", formWidgetClass, toplevel, NULL,
  868.             0);
  869.     j = 0;
  870.     XtSetArg(args[j], XtNlabel, "Game:               " ); ++j;
  871.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  872.     gamew = XtCreateManagedWidget( "gamew", labelWidgetClass, form,
  873.                         args, j );
  874.  
  875.     j = 0;
  876.     XtSetArg(args[j], XtNlabel, "Hcap/Komi:          " ); ++j;
  877.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  878.     hcapw = XtCreateManagedWidget( "hcapw", labelWidgetClass, form,
  879.                         args, j );
  880.     j = 0;
  881.     XtSetArg(args[j], XtNlabel, "White:              " ); ++j;
  882.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  883.     whitew = XtCreateManagedWidget( "whitew", labelWidgetClass, form,
  884.                         args, j );
  885.     j = 0;
  886.     XtSetArg(args[j], XtNlabel, "Black:              " ); ++j;
  887.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  888.     blackw = XtCreateManagedWidget( "blackw", labelWidgetClass, form,
  889.                         args, j );
  890.     j = 0;
  891.     XtSetArg(args[j], XtNlabel, "Captured:           " ); ++j;
  892.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  893.     captw = XtCreateManagedWidget( "captw", labelWidgetClass, form,
  894.                         args, j );
  895.     j = 0;
  896.     XtSetArg(args[j], XtNlabel, "Captured:           " ); ++j;
  897.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  898.     captb = XtCreateManagedWidget( "captb", labelWidgetClass, form,
  899.                         args, j );
  900.     j = 0;
  901.     XtSetArg(args[j], XtNlabel, "Time:               " ); ++j;
  902.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  903.     timew = XtCreateManagedWidget( "timew", labelWidgetClass, form,
  904.                         args, j );
  905.     j = 0;
  906.     XtSetArg(args[j], XtNlabel, "Time:               " ); ++j;
  907.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  908.     timeb = XtCreateManagedWidget( "timeb", labelWidgetClass, form,
  909.                         args, j );
  910.     j = 0;
  911.     XtSetArg(args[j], XtNlabel, "Last:                                     " ); ++j;
  912.     XtSetArg(args[j], XtNjustify, XtJustifyLeft ); ++j;
  913.     lastw = XtCreateManagedWidget( "lastw", labelWidgetClass, form,
  914.                         args, j );
  915.     j = 0;
  916.     XtSetArg( args[j], XtNgameSize, 19 ); ++j;
  917.     XtSetArg( args[j], XtNcursor, GbCBlackStone); ++j;
  918.     goban = XtCreateManagedWidget( "goban", gobanWidgetClass, bw, args,
  919.             j);
  920.  
  921.     refresh = XtCreateManagedWidget( "refresh", commandWidgetClass, form,
  922.             NULL, 0);
  923.     cursorcolor = XtCreateManagedWidget( "cursorcolor", commandWidgetClass,
  924.             form, NULL, 0);
  925.     clearb = XtCreateManagedWidget( "clearb", commandWidgetClass, form,
  926.             NULL, 0);
  927.     stepf = XtCreateManagedWidget( "stepf", commandWidgetClass, form, NULL,
  928.             0);
  929.     stepb = XtCreateManagedWidget( "stepb", commandWidgetClass, form, NULL,
  930.             0);
  931.     refreshstep = XtCreateManagedWidget( "refreshstep", commandWidgetClass,
  932.             form, NULL, 0);
  933.  
  934.     localrefresh = XtCreateManagedWidget( "localrefresh",
  935.             commandWidgetClass, form, NULL, 0);
  936.     size = XtCreateManagedWidget( "size", commandWidgetClass, form, NULL,    
  937.             0);
  938.     savegame = XtCreateManagedWidget( "savegame", commandWidgetClass,
  939.             form, NULL, 0);
  940.     savecurrent = XtCreateManagedWidget( "savecurrent", commandWidgetClass,
  941.             form, NULL, 0);
  942.     coordinates = XtCreateManagedWidget( "coordinates", commandWidgetClass,
  943.             form, NULL, 0);
  944.     quit = XtCreateManagedWidget( "quit", commandWidgetClass, form, NULL,
  945.             0);
  946.  
  947.     XtAppAddActions (app_context, actions, XtNumber(actions));
  948.  
  949.     XtAddCallback (refresh, XtNcallback, (XtCallbackProc)RefreshHost,
  950.             NULL);
  951.     XtAddCallback (cursorcolor, XtNcallback, (XtCallbackProc)CursorColor,
  952.             NULL); 
  953.     XtAddCallback (clearb, XtNcallback, (XtCallbackProc)ClearBoard, NULL);
  954.     XtAddCallback (stepf, XtNcallback, (XtCallbackProc)StepForward, NULL);
  955.     XtAddCallback (stepb, XtNcallback, (XtCallbackProc)StepBack, NULL);
  956.     XtAddCallback (refreshstep, XtNcallback, (XtCallbackProc)RefreshStep,
  957.             NULL);
  958.     XtAddCallback (localrefresh, XtNcallback, (XtCallbackProc)LocalRefresh,
  959.             NULL);
  960.     XtAddCallback (size, XtNcallback, (XtCallbackProc)SetSize, NULL);
  961.     XtAddCallback (savegame, XtNcallback, (XtCallbackProc)SaveGame,
  962.             (XtPointer)REALMOVE );
  963.     XtAddCallback (savecurrent, XtNcallback, (XtCallbackProc)SaveGame,
  964.             (XtPointer)STEPMOVE );
  965.     XtAddCallback (coordinates, XtNcallback, (XtCallbackProc)SetCoordinates,
  966.             NULL);
  967.     XtAddCallback (quit, XtNcallback, (XtCallbackProc)Quit, NULL);
  968.  
  969.     XtRealizeWidget (toplevel);
  970.  
  971.         XSetStandardProperties( XtDisplay(toplevel), XtWindow(toplevel),
  972.         TITLE, ICONTITLE, NULL, argv, argc, NULL );
  973.  
  974.     SetupBoard();
  975.  
  976.     /* grab keystrokes when mouse is in board or menu windows */
  977. #ifndef NOKEYGRAB
  978.     XtGrabKey( bw, AnyKey, AnyModifier, FALSE, 
  979.         GrabModeAsync, GrabModeAsync );
  980.     XtAddEventHandler( bw, KeyPressMask | KeymapStateMask, FALSE, 
  981.         (XtEventHandler)keyevent, NULL );
  982.  
  983.     XtGrabKey(toplevel, AnyKey, AnyModifier, FALSE, 
  984.         GrabModeAsync, GrabModeAsync);
  985.     XtAddEventHandler(toplevel, KeyPressMask | KeymapStateMask, FALSE, 
  986.         (XtEventHandler)keyevent, NULL);
  987. #endif /* NOKEYGRAB */
  988.  
  989.     setup_filter( &exec_stdin, &exec_stdout, &exec_stderr );
  990.     input0id = XtAppAddInput( app_context, fileno(stdin),
  991.         (XtPointer)(XtInputReadMask), read_kbd,
  992.         (caddr_t)fileno(stdin) );
  993.     input1id = XtAppAddInput( app_context, fileno(exec_stdout),
  994.         (XtPointer)(XtInputReadMask), read_filter,
  995.         (caddr_t)fileno(exec_stdout) );
  996.     input2id = XtAppAddInput( app_context, fileno(exec_stderr),
  997.         (XtPointer)(XtInputReadMask), read_filter,
  998.         (caddr_t)fileno(exec_stderr) );
  999.  
  1000.     XtAppAddTimeOut( XtWidgetToApplicationContext(toplevel), 1000, Ticker,
  1001.              XtWidgetToApplicationContext(toplevel) );
  1002.     XtAppMainLoop (app_context);
  1003. }
  1004.  
  1005. Xsetup_p( fr, fw, fe )
  1006.     FILE *fr, *fw, *fe;
  1007. {
  1008.     i1id = XtAppAddInput( app_context, fileno(fw),
  1009.         (XtPointer)(XtInputReadMask), read_pipe,
  1010.         (caddr_t)fileno(fw) );
  1011.     i2id = XtAppAddInput( app_context, fileno(fe),
  1012.         (XtPointer)(XtInputReadMask), read_pipe,
  1013.         (caddr_t)fileno(fe) );
  1014.     if( dbg ) {
  1015.         fprintf( stderr, "Xsetup_p: i1id=0x%x, i2id=0x%x\n", i1id, i2id );
  1016.         fflush( stderr );
  1017.     }
  1018. }
  1019.  
  1020. Xclose_p() {
  1021.     XtRemoveInput( i1id );
  1022.     XtRemoveInput( i2id );
  1023. }
  1024.  
  1025. void read_pipe( client_data, source, id )
  1026.     int client_data;
  1027.     int *source;
  1028.     char *id;
  1029. {
  1030.     unsigned char str[LINESIZE+1];
  1031.     int ret;
  1032.  
  1033.     ret = read( client_data, str, LINESIZE );
  1034.     if( ret == (-1) ) perror( "read_pipe" );
  1035.  
  1036.     if( dbg ) {
  1037.         fprintf( stderr, "ENTER read_pipe [%d]\n", ret );
  1038.         fflush( stderr );
  1039.     }
  1040.  
  1041.     if( ret <= 0 ) return;
  1042.     else str[ret] = '\0';
  1043.     
  1044.     fprintf( stderr, "%s", str );
  1045.     fflush( stderr );
  1046. }
  1047.     
  1048.  
  1049. /* this one reads input from the comm channel, prints it, and also
  1050.  * calls process_input for parsing
  1051.  */
  1052. void read_filter( client_data, source, id )
  1053.     int client_data;
  1054.     int *source;
  1055.     char *id;
  1056. {
  1057.     unsigned char str[LINESIZE+1], *s;
  1058.     int ret, i, code;
  1059.  
  1060.     ret = read( client_data, str, LINESIZE );
  1061.     if( ret <= 0 ) {
  1062. /* these lines don't really do anything very useful,
  1063.  * and they cause problems on some HP 9000 systems
  1064.         XtRemoveInput( input1id );
  1065.         XtRemoveInput( input2id );
  1066.         fprintf( stderr, "Closing pipes to comm process\n" );
  1067. SC*/
  1068.         return;
  1069.     }
  1070.     else str[ret] = '\0';
  1071.  
  1072.     if( dbg ) fprintf( stderr,
  1073.         "********* in read_filter() fd=%d **********\n", client_data );
  1074.  
  1075.     /* just check once more to be sure we have only 7-bit chars */
  1076.     for( i=0; i<ret; ++i ) str[i] &= 0x7f;
  1077.  
  1078.     process_input( str );
  1079.  
  1080.     if( dbg ) fprintf( stderr,
  1081.         "######### leave read_filter() [%d chars] #########\n", ret );
  1082. }
  1083.  
  1084. /* this one just reads lines from the kbd and passes them to comm stdin */
  1085. void read_kbd( client_data, source, id )
  1086.     int client_data;
  1087.     int *source;
  1088.     char *id;
  1089. {
  1090.     unsigned char str[LINESIZE+1];
  1091.     int ret;
  1092.  
  1093.     if( dbg ) fprintf( stderr,
  1094.         "********* in read_kbd() fd=%d **********\n", client_data );
  1095.     ret = read( client_data, str, LINESIZE );
  1096.     if( ret <= 0 ) {
  1097.         fprintf( stderr, "\nKBD: no input!  (ignored)\n" );
  1098.         return;
  1099.     }
  1100.     else str[ret] = '\0';
  1101.  
  1102.     /*XXX got to do something about the CTRL-P to make it work right
  1103.      * when cursor is in xterm window
  1104.      */
  1105.  
  1106.     process_kbd( str, exec_stdin );
  1107.  
  1108.     if( dbg ) fprintf( stderr,
  1109.         "######### leave read_kbd() [%d chars] #########\n", ret );
  1110. }
  1111.  
  1112. setMark( i, j, t )
  1113.     int i, j;
  1114.     unsigned char t;
  1115. {
  1116.     GbSetMark( goban, (Position)i, (Position)j, t, 0 );
  1117. }
  1118.  
  1119. drawStone( i, h, t, flag )
  1120.     int i, h;
  1121.     int t;    /* 0=remove, 1=black, 2=white */
  1122.     unsigned char flag;
  1123. {
  1124.     if( dbg ) fprintf( stderr, "Drawing stone at %d,%d  (%d)\n", i, h, t );
  1125.     GbSetPoint( goban, i, h, t, flag );
  1126. }
  1127.  
  1128. update_status( g, black, white, bcapt, wcapt, btime, wtime, bbyo, wbyo, rankw,
  1129.         rankb )
  1130.     int g;
  1131.     unsigned char *white, *black;
  1132.     int wcapt, bcapt, wtime, btime;
  1133.     int bbyo, wbyo;
  1134.     char *rankw, *rankb;
  1135. {
  1136.     Arg args[8];
  1137.     int j;
  1138.     unsigned char str[80];
  1139.  
  1140.     update_gameno( g );
  1141.  
  1142.     if( g < 0 ) sprintf( (char *)str, "Black:" );
  1143.     else if( (int)strlen( (char *)rankb ) <= 0 ) 
  1144.         sprintf( (char *)str, "Black: %s", black );
  1145.     else sprintf( (char *)str, "Black: %s    %s", black, rankb );
  1146.     j = 0;
  1147.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1148.     XtSetValues( blackw, args, j );
  1149.  
  1150.     if( g < 0 ) sprintf( (char *)str, "White:" );
  1151.     else if( (int)strlen( (char *)rankw ) <= 0 ) 
  1152.         sprintf( (char *)str, "White: %s", white );
  1153.     else sprintf( (char *)str, "White: %s    %s", white, rankw );
  1154.     j = 0;
  1155.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1156.     XtSetValues( whitew, args, j );
  1157.  
  1158.     if( g < 0 ) sprintf( (char *)str, "Captured:" );
  1159.     else sprintf( (char *)str, "Captured:   %d", wcapt );
  1160.     j = 0;
  1161.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1162.     XtSetValues( captw, args, j );
  1163.  
  1164.     if( g < 0 ) sprintf( (char *)str, "Captured:" );
  1165.     else sprintf( (char *)str, "Captured:   %d", bcapt );
  1166.     j = 0;
  1167.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1168.     XtSetValues( captb, args, j );
  1169.  
  1170.     fix_wtime( wtime, wbyo );
  1171.     fix_btime( btime, bbyo );
  1172. }
  1173.  
  1174. update_move( last )
  1175.     unsigned char *last;
  1176. {
  1177.     int i, j;
  1178.     unsigned char str[80];
  1179.     Arg args[8];
  1180.  
  1181.     if( last == NULL ) sprintf( (char *)str, "Last:" );
  1182.     else {
  1183.         sprintf( (char *)str, "Last:   %s", last );
  1184.         for( i=0; str[i] != '\0' && str[i] != '\r' && str[i] != '\n'; ++i );
  1185.         str[i] = '\0';
  1186.     }
  1187.  
  1188.     j = 0;
  1189.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1190.     XtSetValues( lastw, args, j );
  1191. }
  1192.  
  1193. update_handicap( hcap, komi )
  1194.     int hcap;
  1195.     float komi;
  1196. {
  1197.     Arg args[8];
  1198.     int j;
  1199.     unsigned char str[80];
  1200.  
  1201.     if( hcap < 0 ) sprintf( (char *)str, "Hcap/Komi:" );
  1202.     else sprintf( (char *)str, "Hcap/Komi:    %d   /   %2.1f", hcap, komi );
  1203.     j = 0;
  1204.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1205.     XtSetValues( hcapw, args, j );
  1206. }
  1207.  
  1208. update_gameno( g )
  1209.     int g;
  1210. {
  1211.     Arg args[8];
  1212.     int j;
  1213.     unsigned char str[80];
  1214.  
  1215.     if( g < 0 ) sprintf( (char *)str, "Game:" );
  1216.     else sprintf( (char *)str, "Game:   %d", g );
  1217.     j = 0;
  1218.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1219.     XtSetValues( gamew, args, j );
  1220. }
  1221.  
  1222. /* get the server config file, with command line to execute, if any
  1223.  * return (-1) if no
  1224.  *    1) a file $HOME/.xigcrc
  1225.  *    2) in this file:
  1226.  *        COMMAND   cmd line to execute
  1227.  *        QUITCOMMAND cmd to quit from "cmd"
  1228.  *        SAVEFORMAT  SGF or TEXT format for "Save game" menu item
  1229.  *        TERSEMODE true or false
  1230.  *        SAVEDIR full path of directory to save games into
  1231.  *        SORTWHO sorts "who" output by player rank
  1232.  */
  1233. static int get_cmd() {
  1234.     unsigned char *ret;
  1235.     FILE *fp;
  1236.     unsigned char str[80];
  1237.     int cnt = 0;
  1238.     extern char *getenv();
  1239.     int len;
  1240.  
  1241.     cmd[0] = '\0';
  1242.     quitcmd[0] = '\0';
  1243.     strcpy( (char *)savedir, "." );
  1244.  
  1245.     ret = (unsigned char *)getenv( "HOME" );
  1246.     if( ret == NULL ) return( cnt );
  1247.  
  1248.     sprintf( (char *)str, "%s/.xigcrc", ret );
  1249.     if( dbg ) fprintf( stderr, "config file: >>%s<<\n", str );
  1250.     fp = fopen( (char *)str, "r" );
  1251.     if( fp  == NULL ) {
  1252.         if( dbg ) fprintf( stderr, "can't open config file >>%s<<\n", str );
  1253.         return( cnt );
  1254.     }
  1255.     
  1256.     while( fgets( (char *)str, 80, fp ) != NULL ) {
  1257.         len = strlen( (char *)str );
  1258.         if( len < 4 || str[0] == '#' ) continue;
  1259.         str[len-1] = '\0';
  1260.         if( dbg ) fprintf( stderr, ">>%s<<\n", str );
  1261.         if( strncmp( (char *)str, "COMMAND", 7 ) == 0 ) {
  1262.         if( cmd[0] == '\0' ) {
  1263.             strcpy( (char *)cmd, (char *)&str[8] );
  1264.             if( dbg ) fprintf( stderr, "get_cmd: cmd >>%s<<\n" , cmd );
  1265.             ++cnt;
  1266.         }
  1267.         }
  1268.         if( strncmp( (char *)str, "QUITCOMMAND", 11 ) == 0 ) {
  1269.         if( quitcmd[0] == '\0' ) {
  1270.             strcpy( (char *)quitcmd, (char *)&str[12] );
  1271.             if( dbg ) fprintf( stderr, "get_cmd: quitcmd >>%s<<\n",
  1272.                     quitcmd );
  1273.             ++cnt;
  1274.             }
  1275.         }
  1276.         if( strncmp( (char *)str, "TERSEMODE", 9 ) == 0 ) {
  1277.             if( strncmp( (char *)&str[10], "TRUE", 4 ) == 0 ||
  1278.                 strncmp( (char *)&str[10], "true", 4 ) == 0 )
  1279.                 tersemode = TRUE;
  1280.             else if( strncmp( (char *)&str[10], "FALSE", 5 ) == 0 ||
  1281.                 strncmp( (char *)&str[10], "false", 5 ) == 0 )
  1282.                 tersemode = FALSE;
  1283.             ++cnt;
  1284.         }
  1285.         if( strncmp( (char *)str, "SORTWHO", 7 ) == 0 ) {
  1286.             if( strncmp( (char *)&str[8], "TRUE", 4 ) == 0 ||
  1287.                 strncmp( (char *)&str[8], "true", 4 ) == 0 )
  1288.                 sortwhomode = TRUE;
  1289.             else if( strncmp( (char *)&str[8], "FALSE", 5 ) == 0 ||
  1290.                 strncmp( (char *)&str[8], "false", 5 ) == 0 )
  1291.                 sortwhomode = FALSE;
  1292.             ++cnt;
  1293.         }
  1294.         if( strncmp( (char *)str, "SAVEFORMAT", 10 ) == 0 ) {
  1295.             if( strncmp( (char *)&str[11], "TEXT", 4 ) == 0 ||
  1296.                 strncmp( (char *)&str[11], "text", 4 ) == 0 )
  1297.                 saveformat = TEXT;
  1298.             else if( strncmp( (char *)&str[11], "SGF", 3 ) == 0 ||
  1299.                 strncmp( (char *)&str[11], "sgf", 3 ) == 0 )
  1300.                 saveformat = SGF;
  1301.             ++cnt;
  1302.         }
  1303.         if( strncmp( (char *)str, "SAVEDIR", 7 ) == 0 ) {
  1304.         strcpy( (char *)savedir, (char *)&str[8] );
  1305.         ++cnt;
  1306.         }
  1307.     }
  1308.  
  1309.     fclose( fp );
  1310.     return( cnt );
  1311. }
  1312.  
  1313. fix_wtime( wtime, wbyo )
  1314.     int wtime;
  1315.     int wbyo;
  1316. {
  1317.     Arg args[8];
  1318.     int j;
  1319.     unsigned char str[80];
  1320.  
  1321.     if( wbyo > 0 ) {
  1322.         sprintf( (char *)str, "Byo Yomi:   %d:%02.2d    %d",
  1323.         wtime/60, wtime%60, wbyo );
  1324.     }
  1325.     else {
  1326.         sprintf( (char *)str, "Time:   %d:%02.2d", wtime/60, wtime%60 );
  1327.     }
  1328.     j = 0;
  1329.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1330.     XtSetValues( timew, args, j );
  1331. }
  1332.  
  1333. fix_btime( btime, bbyo )
  1334.     int btime, bbyo;
  1335. {
  1336.     Arg args[8];
  1337.     int j;
  1338.     unsigned char str[80];
  1339.  
  1340.     if( bbyo > 0 ) {
  1341.         sprintf( (char *)str, "Byo Yomi:   %d:%02.2d    %d",
  1342.         btime/60, btime%60, bbyo );
  1343.     }
  1344.     else {
  1345.         sprintf( (char *)str, "Time:   %d:%02.2d", btime/60, btime%60 );
  1346.     }
  1347.     j = 0;
  1348.     XtSetArg(args[j], XtNlabel, str ); ++j;
  1349.     XtSetValues( timeb, args, j );
  1350. }
  1351.